package com.fast.alden.admin.service.impl;

import com.fast.alden.admin.service.SysRoleService;
import com.fast.alden.admin.service.SysUserService;
import com.fast.alden.common.service.impl.BaseEntityServiceImpl;
import com.fast.alden.data.model.SysRole;
import com.fast.alden.data.model.SysUser;
import com.fast.alden.data.model.SysUserRole;
import com.fast.alden.data.repo.SysApiResourceRoleRepository;
import com.fast.alden.data.repo.SysMenuRoleRepository;
import com.fast.alden.data.repo.SysRoleRepository;
import com.fast.alden.data.repo.SysUserRoleRepository;
import jakarta.annotation.Resource;
import jakarta.transaction.Transactional;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class SysRoleServiceImpl extends BaseEntityServiceImpl<SysRole, SysRoleRepository> implements SysRoleService {
    @Resource
    private SysRoleRepository repository;
    @Resource
    private SysUserRoleRepository userRoleRepository;
    @Resource
    private SysUserService userService;
    @Resource
    private SysMenuRoleRepository menuRoleRepository;
    @Resource
    private SysApiResourceRoleRepository apiResourceRoleRepository;

    @Override
    protected Class<SysRole> getEClass() {
        return SysRole.class;
    }

    @Override
    protected SysRoleRepository getRepository() {
        return repository;
    }

    @Override
    @Transactional
    public List<SysRole> remove(List<Long> ids) {
        List<SysRole> roles = super.remove(ids);

        // 删除用户-角色关联数据
        userRoleRepository.deleteByRoleIdIn(ids);
        // 删除角色-菜单关联数据
        menuRoleRepository.deleteByRoleIdIn(ids);
        // 删除角色-资源关联数据
        apiResourceRoleRepository.deleteByRoleIdIn(ids);

        return roles;
    }

    @Override
    @Transactional
    public void assign(Long userId, List<Long> roleIds) {
        SysUser user = userService.retrieveWithException(userId);

        List<SysUserRole> existUserRoles = userRoleRepository.findAllByUserIdIsAndRoleIdIn(userId, roleIds);
        List<Long> existRoleIds = existUserRoles.stream().map(SysUserRole::getRoleId).toList();

        List<Long> toAddRoleIds = roleIds.stream().filter(it -> !existRoleIds.contains(it)).toList();

        if (toAddRoleIds.isEmpty()) {
            return;
        }

        List<SysUserRole> toAddUserRoles = toAddRoleIds.stream().map(it -> {
            SysUserRole userRole = new SysUserRole();
            userRole.setUserId(userId);
            userRole.setRoleId(it);
            return userRole;
        }).toList();

        userRoleRepository.saveAll(toAddUserRoles);
    }

    @Override
    @Transactional
    public void cancelAssign(Long userId, List<Long> roleIds) {
        SysUser user = userService.retrieveWithException(userId);

        List<SysUserRole> existUserRoles = userRoleRepository.findAllByUserIdIsAndRoleIdIn(userId, roleIds);

        if (existUserRoles.isEmpty()) {
            return;
        }

        userRoleRepository.deleteAll(existUserRoles);
    }

    @Override
    public List<SysRole> findAllByUserId(Long userId) {
        List<SysUserRole> userRoles = userRoleRepository.findAllByUserIdIs(userId);
        List<Long> roleIds = userRoles.stream().map(SysUserRole::getRoleId).toList();
        return repository.findAllById(roleIds);
    }

    @Override
    public List<SysRole> findRolesByUserId(Long userId) {
        List<SysUserRole> userRoles = userRoleRepository.findAllByUserIdIs(userId);
        List<Long> roleIds = userRoles.stream().map(SysUserRole::getRoleId).toList();
        return list(roleIds);
    }
}
